<?php

class LightPressModRewrite {
    
    var $basedir;
    var $_rootdir;
    var $_htaccess;
    var $_lighty;
    var $_base;
    var $_lp_base;
    var $_wp_base;
    var $_archive_prefix;
    var $_post_prefix;
    var $_post_vars;
    
    // the following are just in case we ever find a way to decode the archive permalink
    // built using strftime, as we currently only support %Y and %m
    var $_strftime_formats = array(
        '%b'    => '[a-zA-Z]+',       // abbreviated month name according to the current locale
        '%B'    => '[a-zA-Z]+',       // full month name according to the current locale
        '%C'    => '[0-9]{2}',     // century number (the year divided by 100 and truncated to an integer, range 00 to 99)
        '%h'    => '[a-zA-Z]+',       // same as %b
        '%m'    => '([0-9]{2})',   // month as a decimal number (range 01 to 12)
        '%d'    => '([0-9]{2})',   // day as a decimal number (range 01 to 31)
        '%U'    => '[0-9]{1,2}',   // week number of the current year as a decimal number, starting with the first Sunday as the first day of the first week
        '%V'    => '[0-9]{2}',     // The ISO 8601:1988 week number of the current year as a decimal number, range 01 to 53, where week 1 is the first week that has at least 4 days in the current year, and with Monday as the first day of the week. (Use %G or %g for the year component that corresponds to the week number for the specified timestamp.)
        '%W'    => '[0-9]{1,2}',   // week number of the current year as a decimal number, starting with the first Monday as the first day of the first week
        '%y'    => '([0-9]{2})',   // year as a decimal number without a century (range 00 to 99)
        '%Y'    => '([0-9]{4})'    // year as a decimal number including the century
        );
    
    var $_strftime_verbs = array(   // for conversion from selected verbs below to formats above
        '{year}'      => '%Y',
        '{monthnum}'  => '%m', 
        '{day}'       => '%d',
        '{hour}'      => '%H',
        '{minute}'    => '%M',
        '{second}'    => '%S'
        );
    
    var $_permalink_verbs = array(
        'year'          => '[0-9]{4}', 
        'monthnum'      => '[0-9]{2}', 
        'day'           => '[0-9]{2}',
        'hour'          => '[0-9]{2}',
        'minute'        => '[0-9]{2}',
        'second'        => '[0-9]{2}',
        'postname'      => '([-a-zA-Z0-9_]+)',
        'post_name'     => '([-a-zA-Z0-9_]+)',
        'post_id'       => '([0-9]+)',
        'category_id'   => '[0-9]+',
        'category_name' => '[-a-zA-Z0-9_]+',
        'author'        => ''   // unsupported for now, since it requires an additional JOIN in plugins
        );
    
    function LightPressModRewrite() {
        $basedir = get_option('lp_opt_basedir');
        if (!$basedir) {
            // trigger_error('LightPress active with no options set (null basedir), skipping LightPress .htaccess filter', E_USER_WARNING);
        }
        $this->basedir = $basedir;
        $this->_rootdir = dirname(dirname(dirname($basedir)));
        $parsed_url = parse_url(get_option('siteurl'));
        if (!isset($parsed_url['path']))
            $parsed_url['path'] = '';
        $this->_lp_base = $parsed_url['path'];
        $parsed_url = parse_url(get_option('home'));
        if (!isset($parsed_url['path']))
            $parsed_url['path'] = '';
        $this->_base = $parsed_url['path'];
    }
    
    function WPsubdirs() {
        if (!is_null($this->_wp_base))
            return $this->_wp_base;
        // find WP subdir(s)
        $url = get_option('lp_opt_url');
        $wp_url = get_option('lp_opt_wp_url');
        $pos = strpos($wp_url, $url);
        if (($url != $wp_url) && ($pos !== false)) {
            $pos += strlen($url) + 1;
            $base = substr($wp_url, $pos);
            if (substr($base, -1) != '/')
                $base .= '/';
        } else {
            $base = '';
        }
        $this->_wp_base =& $base;
        return $base;
    }
    
    function buildHtaccess() {
        // TODO: refactor this thing
        $this->_htaccess = '';
        $ht =& $this->_htaccess;
        $ht .= "<IfModule mod_rewrite.c>\nRewriteEngine On\n";
        $parsed_url = parse_url(get_option('siteurl'));
        if (!isset($parsed_url['path']))
            $parsed_url['path'] = '';
        $lp_base = $this->_lp_base . '/wp-content/plugins/lightpress';
        $ht .= "RewriteBase {$lp_base}\n";
        $ht .= 'RewriteCond %{REQUEST_FILENAME} -f [OR]' . "\n";
        $ht .= 'RewriteCond %{REQUEST_FILENAME} -d' . "\n";
        $ht .= $this->_getIndexRules();
        $ht .= $this->_getFeedRules();
        $ht .= $this->_getTagRules();
        $ht .= $this->_getCategoryRules();
        $ht .= $this->_getArchiveRules();
        $ht .= $this->_getPostRules();
        $ht .= $this->_getEndRules();
        $ht .= "\n</IfModule>\n";
        return $ht;
    }
    
    function buildLightHttpd() {

        $base = $this->_base;
        $lp_base = $this->_lp_base;
        if (substr($lp_base, 0, 1) != '/')
            $lp_base = '/' . $lp_base;
        $rules = array();
        
        // index
        $rules['# index'] = '';
        $rules['^' . $base . '/?$'] = 'index.php';
        $rules['^' . $base . '/record/([0-9]+)/?$'] = 'index.php?i=$1';
        // feeds
        $rules['# feeds'] = '';
        $rules['^' . $base . '/rss2.xml'] = 'feed.php';
        $rules['^' . $base . '/atom.xml'] = 'feed.php?feed=atom';
        $rules['^' . $base . '/feed$'] = 'feed.php';
        $rules['^' . $base . '/feed/?(feed|rss|rss2|rdf|atom)/?$'] = 'feed.php?feed=$1';
        $wp_base = $this->WPsubdirs();
        $rules['^' . $base . '/' . $wp_base . 'wp-atom.php'] = 'feed.php';
        $rules['^' . $base . '/' . $wp_base . 'wp-rss.php'] = 'feed.php';
        $rules['^' . $base . '/' . $wp_base . 'wp-rss2.php'] = 'feed.php';
        // search
        $prefix = str_replace('?', '\\?', get_option('lp_opt_search_prefix'));
        $rules['# search'] = '';
        $rules['^' . $base . '/' . $prefix . '/?$'] = 'index.php';
        $rules['^' . $base . '/' . $prefix . '/([^/]+)/rss2.xml/?$'] = 'feed.php?q=$1';
        $rules['^' . $base . '/' . $prefix . '/([^/]+)/?$'] = 'index.php?q=$1';
        $rules['^' . $base . '/' . $prefix . '/([^/]+)/record/?([0-9]*)/?$'] = 'index.php?q=$1&i=$2';
        // author
        $prefix = str_replace('?', '\\?', get_option('lp_opt_author_prefix'));
        $rules['# author'] = '';
        $rules['^' . $base . '/' . $prefix . '/?$'] = 'index.php';
        $rules['^' . $base . '/' . $prefix . '/([^/]+)/rss2.xml/?$'] = 'feed.php?u=$1';
        $rules['^' . $base . '/' . $prefix . '/([^/]+)/?$'] = 'index.php?u=$1';
        $rules['^' . $base . '/' . $prefix . '/([^/]+)/record/?([0-9]*)/?$'] = 'index.php?u=$1&i=$2';
        // stats
        $rules['# stats'] = '';
        $rules['^' . $base . '/stats.gif$'] = 'stats.php';
        // extended archives and categories
        $rules['# extended archives and categories'] = '';
        $rules['^' . $base . '/archives/?$'] = 'list_archives.php';
        $rules['^' . $base . '/categories/?$'] = 'list_categories.php';
        // sitemaps
        $rules['# sitemaps'] = '';
        $rules['^' . $base . '/sitemap.xml'] = 'sitemap.php?sitemap=1';
        $rules['^' . $base . '/sitemap_index.xml'] = 'sitemap.php';
        // tags
        $prefix = str_replace('?', '\\?', get_option('lp_opt_tag_prefix'));
        $rules['# tags'] = '';
        $rules['^' . $base . '/' . $prefix . '/(.+)/rss2.xml$'] = 'feed.php?tag=$1';
        $rules['^' . $base . '/' . $prefix . '/(.+)/atom.xml$'] = 'feed.php?tag=$1&feed=atom';
        $rules['^' . $base . '/' . $prefix . '/(.+)/record/?([0-9]*)/?$'] = 'index.php?tag=$1&i=$2';
        $rules['^' . $base . '/' . $prefix . '/(.+)/?$'] = 'index.php?tag=$1';
        // categories
        $prefix = str_replace('?', '\\?', get_option('lp_opt_category_prefix'));
        $rules['# categories'] = '';
        $rules['^' . $base . '/' . $prefix . '/([^/]+)/?$'] = 'index.php?c=$1';
        $rules['^' . $base . '/' . $prefix . '/([^/]+)/record/?([0-9]*)/?$'] = 'index.php?c=$1&i=$2';
        $rules['^' . $base . '/' . $prefix . '/([^/]+)/rss2.xml$'] = 'feed.php?c=$1';
        $rules['^' . $base . '/' . $prefix . '/([^/]+)/atom.xml$'] = 'feed.php?c=$1&feed=atom';
        $rules['^' . $base . '/' . $prefix . '/([^/]+)/sitemap.xml$'] = 'sitemap.php?c=$1&sitemap=1';
        // archives
        $prefix =& $this->getArchivePrefix();
        $rules['# archives'] = '';
        $rules['^' . $base . '/' . $prefix . '/?$'] = 'index.php?y=$1&m=$2&d=$3';
        $rules['^' . $base . '/' . $prefix . '/record/?([0-9]*)/?$'] = 'index.php?y=$1&m=$2&d=$3&i=$4';
        $rules['^' . $base . '/' . $prefix . '/sitemap.xml$'] = 'sitemap.php?y=$1&m=$2&d=$3&sitemap=1';
        // posts
        list($prefix, $get_vars) = $this->getPostPrefix();
        $rules['# posts'] = '';
        // posts - base rule
        $rules['^' . $base . '/' . $prefix . '/?$'] = 'index.php?' . implode('&', $get_vars);
        // posts - comment submission
        $rules['^' . $base . '/' . $prefix . '/?\?(.*)$'] = 'index.php?' . implode('&', $get_vars) . '&$' . (count($get_vars) + 1);
        // posts - anchor
        $rules['^' . $base . '/' . $prefix . '/?(#.*)$'] = 'index.php?' . implode('&', $get_vars) . '$' . (count($get_vars) + 1);
        $rules['^' . $base . '/trackback/([^/]+)/?$'] = 'index.php?p=$1&action=trackback';
        // short-circuit /wp-admin
        $rules['# short-circuit wp-admin'] = '';
        $rules['^' . $lp_base . '/wp-admin/?(.*)$'] = $base . '/wp-admin/$1';
        // pages
        $rules['# pages'] = '';
        $rules['# to exclude URLs from the eat-all page rules, add to the negative lookbehind assertions below'] = '';
        $rules['# eg to exclude /styles/any_file use (?<!wp-|styles)'] = '';
        $rules['# be careful not to use the same words as the first characters for page slugs, as they won\'t work'] = '';
        $rules['# URLs pointing to files with an extension (eg /style.css) are automatically skipped by the page rules'] = '';
        $prefix = str_replace('?', '\\?', get_option('lp_opt_pages_prefix'));
        $suffix = get_option('lp_opt_pages_suffix');
        if ($prefix) {
            $rules['^' . $base . '/' . $prefix . '/([^/]+)' . $suffix . '/?$'] = 'index.php?s=$1';
        } else {
            $rules['^' . $base . '/(?<!wp-)([^/.]+)/?$'] = 'index.php?y1=$1';
            $rules['^' . $base . '/(?<!wp-)([^/.]+)/?\?(.*)$'] = 'index.php?y1=$1&$2';
            $rules['^' . $base . '/(?<!wp-)([^/.]+)/?(#.*)$'] = 'index.php?y1=$1$2';
            $rules['^' . $base . '/(?<!wp-)([^/.]+)/([^/.]+)/?$'] = 'index.php?y1=$1&y2=$2';
            $rules['^' . $base . '/(?<!wp-)([^/.]+)/([^/.]+)/?\?(.*)$'] = 'index.php?y1=$1&y2=$2&$3';
            $rules['^' . $base . '/(?<!wp-)([^/.]+)/([^/.]+)/?(#.*)$'] = 'index.php?y1=$1&y2=$2$3';
            $rules['^' . $base . '/(?<!wp-)([^/.]+)/([^/.]+)/([^/.]+)/?$'] = 'index.php?y1=$1&y2=$2&y3=$3';
            $rules['^' . $base . '/(?<!wp-)([^/.]+)/([^/.]+)/([^/.]+)/?\?(.*)$'] = 'index.php?y1=$1&y2=$2&y3=$3&$4';
            $rules['^' . $base . '/(?<!wp-)([^/.]+)/([^/.]+)/([^/.]+)/?(#.*)$'] = 'index.php?y1=$1&y2=$2&y3=$3$4';
        }
        $lp_base .= '/wp-content/plugins/lightpress/';
        $lt = "# rewrite rules for Lightpress at\n";
        $lt .= "# " . get_option('home') . ' WP admin URL ' . get_option('siteurl') . "\n";
        $lt .= "url.rewrite-once = (\n";
        foreach ($rules as $k=>$v) {
            if ($k[0] == '#')
                $lt .= "\t$k\n";
            else if (strpos($v, 'wp-admin') !== false)
                $lt .= sprintf("\t%s => \"%s\",\n", str_pad('"' . $k . '"', 60), $v);
            else
                $lt .= sprintf("\t%s => \"{$lp_base}%s\",\n", str_pad('"' . $k . '"', 60), $v);
        }
        $lt .= ")";
        $this->_lighty =& $lt;
        return $lt;
    }
    
    function _getIndexRules() {
        $ht = "\n# index page\n";
        $ht .= 'RewriteRule ^/?$ index.php [QSA,L]' . "\n";
        $ht .= 'RewriteRule ^record/([0-9]+)/?$ index.php?i=$1 [QSA,L]' . "\n";
        $prefix = str_replace('?', '\\?', get_option('lp_opt_search_prefix'));
        $ht .= 'RewriteRule ^' . $prefix . '/?$ index.php [QSA,L]' . "\n";
        $ht .= 'RewriteRule ^' . $prefix . '/([^/]+)/rss2.xml/?$ feed.php?q=$1 [QSA,L]' . "\n";
        $ht .= 'RewriteRule ^' . $prefix . '/([^/]+)/?$ index.php?q=$1 [QSA,L]' . "\n";
        $ht .= 'RewriteRule ^' . $prefix . '/([^/]+)/record/?([0-9]*)/?$ index.php?q=$1&i=$2 [QSA,L]' . "\n";
        $prefix = str_replace('?', '\\?', get_option('lp_opt_author_prefix'));
        $ht .= 'RewriteRule ^' . $prefix . '/?$ index.php [QSA,L]' . "\n";
        $ht .= 'RewriteRule ^' . $prefix . '/([^/]+)/rss2.xml/?$ feed.php?u=$1 [QSA,L]' . "\n";
        $ht .= 'RewriteRule ^' . $prefix . '/([^/]+)/?$ index.php?u=$1 [QSA,L]' . "\n";
        $ht .= 'RewriteRule ^' . $prefix . '/([^/]+)/record/?([0-9]*)/?$ index.php?u=$1&i=$2 [QSA,L]' . "\n";
        $ht .= "\n";
        $ht .= "# stats\n";
        $ht .= 'RewriteRule ^stats.gif$ stats.php [QSA,L]' . "\n";
        $ht .= "# archives list\n";
        $ht .= 'RewriteRule ^archives/?$ list_archives.php [QSA,L]' . "\n";
        $ht .= "# categories list\n";
        $ht .= 'RewriteRule ^categories/?$ list_categories.php [QSA,L]' . "\n";
        return $ht;
    }
    
    function _getFeedRules() {
        
        $ht = "\n#feeds\n";
        # feeds
        $ht .= 'RewriteRule ^rss2.xml feed.php [L]' . "\n";
        $ht .= 'RewriteRule ^atom.xml feed.php?feed=atom [L]' . "\n";
        $ht .= 'RewriteRule ^sitemap.xml sitemap.php?sitemap=1 [QSA,L]' . "\n";
        $ht .= 'RewriteRule ^sitemap_index.xml sitemap.php [L]' . "\n";
        $ht .= "# feeds (WP compatibility)\n";
        $base = $this->WPsubdirs();
        $ht .= 'RewriteRule ^' . $base . 'wp-atom.php feed.php [L]' . "\n";
        $ht .= 'RewriteRule ^' . $base . 'wp-rss.php feed.php [L]' . "\n";
        $ht .= 'RewriteRule ^' . $base . 'wp-rss2.php feed.php [L]' . "\n";
        $ht .= 'RewriteRule ^feed$ feed.php [L]' . "\n";
        $ht .= 'RewriteRule ^feed/?(feed|rss|rss2|rdf|atom)/?$ feed.php?feed=$1 [QSA,L]' . "\n";
        return $ht;
    }
    
    function _getTagRules() {
        $prefix = str_replace('?', '\\?', get_option('lp_opt_tag_prefix'));
        $ht = "\n# tag searches\n";
        $ht .= 'RewriteRule ^' . $prefix . '/(.+)/rss2.xml$ feed.php?tag=$1 [QSA,L]' . "\n";
        $ht .= 'RewriteRule ^' . $prefix . '/(.+)/atom.xml$ feed.php?tag=$1&feed=atom [QSA,L]' . "\n";
        $ht .= 'RewriteRule ^' . $prefix . '/(.+)/record/?([0-9]*)/?$ index.php?tag=$1&i=$2 [QSA,L]' . "\n";
        $ht .= 'RewriteRule ^' . $prefix . '/(.+)/?$ index.php?tag=$1 [QSA,L]' . "\n";
        return $ht;
    }
    
    function _getCategoryRules() {
        $prefix = str_replace('?', '\\?', get_option('lp_opt_category_prefix'));
        $ht = "\n# categories\n";
        $ht .= 'RewriteRule ^' . $prefix . '/([^/]+)/?$ index.php?c=$1 [QSA,L]' . "\n";
        $ht .= 'RewriteRule ^' . $prefix . '/([^/]+)/record/?([0-9]*)/?$ index.php?c=$1&i=$2 [QSA,L]' . "\n";
        $ht .= 'RewriteRule ^' . $prefix . '/([^/]+)/rss2.xml$ feed.php?c=$1 [QSA,L]' . "\n";
        $ht .= 'RewriteRule ^' . $prefix . '/([^/]+)/atom.xml$ feed.php?c=$1&feed=atom [QSA,L]' . "\n";
        $ht .= 'RewriteRule ^' . $prefix . '/([^/]+)/sitemap.xml$ sitemap.php?c=$1&sitemap=1 [QSA,L]' . "\n";
        return $ht;
    }

    function &getArchivePrefix() {
        if (!is_null($this->_archive_prefix))
            return $this->_archive_prefix;
        $prefix = str_replace('?', '\\?', get_option('lp_opt_archives_prefix'));
        $prefix = str_replace(
            array_keys($this->_strftime_verbs),
            array_values($this->_strftime_verbs),
            $prefix);
        $prefix = str_replace(
            array_keys($this->_strftime_formats),
            array_values($this->_strftime_formats),
            $prefix);
        $this->_archive_prefix =& $prefix;
        return $prefix;
    }
    
    function _getArchiveRules() {
        // we assume %Y and %m never swap position
        // TODO: find a way to interpret a few more strftime codes
        //       and detect the position of %Y %m to correctly place
        //       y=$n m=$n
        $prefix =& $this->getArchivePrefix();
        $ht = "\n# archives\n";
        $ht .= 'RewriteRule ^' . $prefix . '/?$ index.php?y=$1&m=$2 [QSA,L]' . "\n";
        $ht .= 'RewriteRule ^' . $prefix . '/record/?([0-9]*)/?$ index.php?y=$1&m=$2&i=$3 [QSA,L]' . "\n";
        $ht .= 'RewriteRule ^' . $prefix . '/sitemap.xml$ sitemap.php?y=$1&m=$2&sitemap=1 [QSA,L]' . "\n";
        return $ht;
    }

    function getPostPrefix() {
        if (!is_null($this->_post_prefix))
            return array($this->_post_prefix, $this->_post_vars);
        $prefix = str_replace('?', '\\?', get_option('lp_opt_post_prefix'));
        $get_vars = array();
        $m = array();
        preg_match_all('/{([^}]+)}/', $prefix, $m, PREG_SET_ORDER);
        foreach ($m as $match) {
            list($curly_token, $token) = $match;
            if (!isset($this->_permalink_verbs[$token]))
                continue;
            $prefix = str_replace($curly_token, $this->_permalink_verbs[$token], $prefix);
            switch ($token) {
                case 'postname':
                case 'post_name':
                    $get_vars[] = 'p=$' . (count($get_vars) + 1);
                    break;
                case 'post_id':
                    $get_vars[] = 'pi=$' . (count($get_vars) + 1);
                    break;
            }
        }
        $this->_post_prefix =& $prefix;
        $this->_post_vars =& $get_vars;
        return array($prefix, $get_vars);
    }
        
    function _getPostRules() {
        list($prefix, $get_vars) = $this->getPostPrefix();
        $ht = "\n# posts\n";
        $ht .= 'RewriteRule ^' . $prefix . '/?$ index.php?' . implode('&', $get_vars) . ' [QSA,L]' . "\n";
        $ht .= 'RewriteRule ^trackback/([^/]+)/?$ index.php?p=$1&action=trackback [QSA,L]' . "\n";
        // paged comments
        $comments_prefix = str_replace('?', '\\?', get_option('lp_opt_comments_prefix'));
        if (!$comments_prefix)
            $comments_prefix = 'comments';
        $get_vars[] = 'i=$' . (count($get_vars) + 1);
        $ht .= 'RewriteRule ^' . $prefix . '/' . $comments_prefix . '/([0-9]+)/?$ index.php?' . implode('&', $get_vars) . ' [QSA,L]' . "\n";
        $ht .= 'RewriteRule ^' . $prefix . '/' . $comments_prefix . '/(last)/?$ index.php?' . implode('&', $get_vars) . ' [QSA,L]' . "\n";
        // pages
        $prefix = str_replace('?', '\\?', get_option('lp_opt_pages_prefix'));
        $suffix = get_option('lp_opt_pages_suffix');
        if ($prefix)
            $ht .= 'RewriteRule ^' . $prefix . '/([^/]+)' . $suffix . '/?$ index.php?s=$1 [QSA,L]' . "\n";
        return $ht;
    }
    
    function _getEndRules() {

        $suffix = get_option('lp_opt_pages_suffix');
        if (!$suffix)
            $suffix = '';
        $pre = 'RewriteCond %{REQUEST_FILENAME} !-f' . "\n" .
            'RewriteCond %{REQUEST_FILENAME} !-d' . "\n";
        $ht = '';
        
        # page rules
        $ht .= "\n" . '# page rules' . "\n";
        global $table_prefix, $wpdb;
        $pages = $wpdb->get_results("select distinct post_name from {$table_prefix}posts where post_status='static' and post_parent=0", ARRAY_N);
        
        if (is_array($pages)) {
            $parent_pages = $wpdb->get_results("select distinct p2.post_name from {$table_prefix}posts p inner join {$table_prefix}posts p2 on p2.id=p.post_parent where p.post_status='static' and p2.post_parent=0", ARRAY_N);
            if (is_array($parent_pages)) {
                // ugly, but I'm tired...
                foreach ($parent_pages as $page)
                    $parent_pages[$page[0]] = null;
            } else {
                $parent_pages = array();
            }
            foreach ($pages as $page) {
                $page_name = $page[0];
                $ht .= 'RewriteRule ^' . $page_name . '' . $suffix . '/?$ index.php?s=' . $page_name . ' [QSA,L]' . "\n";
                if (isset($parent_pages[$page_name])) {
                    $ht .= 'RewriteRule ^' . $page_name . '/([^/]+)' . $suffix . '/?$ index.php?y1=' . $page_name . '&y2=$1 [QSA,L]' . "\n";
                    $ht .= 'RewriteRule ^' . $page_name . '/([^/]+)/([^/]+)' . $suffix . '/?$ index.php?y1=' . $page_name . '&y2=$1&y3=$2 [QSA,L]' . "\n";
                }
            }
        }

        # two-level category rules
        $ht .= "\n" . '# two-level category rules' . "\n";
        $categories = $wpdb->get_results("select distinct c2.category_nicename from {$table_prefix}categories c inner join {$table_prefix}categories c2 on c2.cat_id=c.category_parent where c2.category_parent=0", ARRAY_N);
        
        if (is_array($categories)) {
            foreach ($categories as $cat) {
                $cat_name = str_replace(' ', '\\s', $cat[0]);
                $ht .= 'RewriteRule ^' . $cat_name . '/?$ index.php?y1=' . $cat_name . ' [QSA,L]' . "\n";    
                $ht .= 'RewriteRule ^' . $cat_name . '/record/?([0-9]*)/?$ index.php?y1=' . $cat_name . '&i=$1 [QSA,L]' . "\n";    
                $ht .= 'RewriteRule ^' . $cat_name . '/([^/]+)/?$ index.php?y1=' . $cat_name . '&y2=$1 [QSA,L]' . "\n";    
                $ht .= 'RewriteRule ^' . $cat_name . '/([^/]+)/record/?([0-9]*)/?$ index.php?y1=' . $cat_name . '&y2=$1&i=$2 [QSA,L]' . "\n";    
                #$ht .= 'RewriteRule ^' . $cat_name . '/([^/]+)/([^/]+)/?$ index.php?y1=' . $cat_name . '&y2=$1&y3=$2 [QSA,L]' . "\n";    
                #$ht .= 'RewriteRule ^' . $cat_name . '/([^/]+)/([^/]+)/record/?([0-9]*)/?$ index.php?y1=' . $cat_name . '&y2=$1&y3=$2&i=$3 [QSA,L]' . "\n";    
            }
        }
        
        return $ht;
    }
    
    function raiseError($message, $method, $line, $type=E_USER_WARNING) {
        trigger_error(
            sprintf("%s.%s() line %d: %s", get_class($this), $method, $line, $message),
            $type);
    }
  
}

?>
